/**
* 
* Set of event for All event
* Copyright (c) 2009 Ecole Centrale de Nantes IRCCyN  
* Classe: penalityTrace.java 
* see <a href="{@docRoot}/documentation/trace.html">Trace for more information</a>
*  
* @author: Urunuela Richard
* @version 3.2
 
 */
package log;

import java.beans.XMLEncoder;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;



import storm.Entity;
import storm.ISimulationKernel;
import storm.SimulationKernel;
import storm.Processors.Processor;
import storm.Tasks.Task;

public class setTrace {
	
	
	/*
	 * 	public void addLog(Entity E){
		this.listeFile.put(E, E.toString());
	}
	 */
	//public ArrayList<Trace> cpuSet;
//	public ArrayList<Trace> taskSet;
//	public ArrayList<Trace> powerSet;
//	public ArrayList<Trace> messSet;
//	public ArrayList<Trace> penalitySet;
	//public ArrayList<Trace> DVSSet;
	public 	HashSet<Task> Tasks;

	public 	HashSet<Processor> CPUs;	
	public ArrayList<Entity> ListeEntities;
	
	
	public int duration=0;
	private ISimulationKernel Kernel ;
	
	private ObjectOutputStream outCpuSet;
	private FileOutputStream outputCpuSet;
	private File cputmp;

	
	
	private File tasktmp;
	private File powertmp;
	private File messtmp;
	private File penalitytmp;
	private File DVStmp;
	private FileOutputStream outputTaskSet;
	private ObjectOutputStream outTaskSet;
	private FileOutputStream outputpowerSet;
	private ObjectOutputStream outpowerSet;
	private FileOutputStream outputmessSet;
	private ObjectOutputStream outmessSet;
	private FileOutputStream outputDVSSet;
	private ObjectOutputStream outDVSSet;
	private FileOutputStream outputpenalitySet;
	private ObjectOutputStream outpenalitySet;
	
	/**
	 * 
	 * @return
	 */
	public int getDuration() {
		return duration;
	}
	/**
	 * 
	 * @param duration
	 */
	public void setDuration(int duration) {
		this.duration = duration;
	}

	//exec ./Tests/arch/test-1.xml

	
	/**
	 * 
	 * 
	 */
	public setTrace(){
		File dir = new File("/tmp");
		   if (!dir.exists()){
			   dir = new File("./tmp");
			   dir.mkdirs();
		   }
		try {
			this.cputmp = File.createTempFile(this.toString()+"--cputmp--TRACE-STORM-",".tmp",dir);
			outputCpuSet = new FileOutputStream(cputmp);
			outCpuSet = new ObjectOutputStream(outputCpuSet);
			cputmp.deleteOnExit();
			
			this.tasktmp = File.createTempFile(this.toString()+"--tasktmp--TRACE-STORM-",".tmp",dir);
			outputTaskSet = new FileOutputStream(tasktmp);
			outTaskSet = new ObjectOutputStream(outputTaskSet);
			tasktmp.deleteOnExit();
			
			this.powertmp = File.createTempFile(this.toString()+"--powertmp--TRACE-STORM-",".tmp",dir);
			outputpowerSet = new FileOutputStream(powertmp);
			outpowerSet = new ObjectOutputStream(outputpowerSet);
			powertmp.deleteOnExit();
			
			
			this.messtmp = File.createTempFile(this.toString()+"--messtmp--TRACE-STORM-",".tmp",dir);
			outputmessSet = new FileOutputStream(messtmp);
			outmessSet = new ObjectOutputStream(outputmessSet);
			messtmp.deleteOnExit();
			
			this.DVStmp = File.createTempFile(this.toString()+"--DVStmp--TRACE-STORM-",".tmp",dir);
			outputDVSSet = new FileOutputStream(DVStmp);
			outDVSSet = new ObjectOutputStream(outputDVSSet);
			DVStmp.deleteOnExit();
			
			this.penalitytmp = File.createTempFile(this.toString()+"--penalitytmp--TRACE-STORM-",".tmp",dir);
			outputpenalitySet = new FileOutputStream(penalitytmp);
			outpenalitySet = new ObjectOutputStream(outputpenalitySet);
			penalitytmp.deleteOnExit();
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

		
	
		
		//this.cpuSet = new ArrayList<Trace>();
		//this.taskSet = new ArrayList<Trace>();
		//this.powerSet = new ArrayList<Trace>();
		this.Tasks = new HashSet<Task>();
	//	this.messSet = new  ArrayList<Trace>();
		//this.DVSSet = new  ArrayList<Trace>();
		//this.penalitySet = new  ArrayList<Trace>();
		CPUs = new HashSet<Processor>();
	}
	/**
	 * 
	 */
	/*public void toXml(){
		this.toXml("");
	}*/
	/**
	 * 
	 * @param nameFile
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
/*	public void toXml(String nameFile){
		XMLEncoder e=new XMLEncoder(System.out);
		
		try {
			if (nameFile.length() > 1) e = new XMLEncoder(new BufferedOutputStream(new FileOutputStream(nameFile)));
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}

		int j =0;
		Iterator i= this.ListeEntities.iterator();
		while (i.hasNext()){
			Entity E =(Entity) i.next();

			 e.writeObject(E);
		}
		
		/**
		 * Trace
		 */
		/*i = this.cpuSet.iterator();
		while(i.hasNext()){
			
			e.writeObject(i.next());
		}
		
		
		e.close();
	

	}*/
	protected ArrayList getArrayfromF(File  cputmp2) {
		ArrayList res = new ArrayList ();
	
		FileInputStream fis;
		try {
			fis = new FileInputStream(cputmp2);

		ObjectInputStream ois = new ObjectInputStream(fis);
	
		while (true) {  
			
			try {
				Object obj = ois.readObject();
				
				Trace T = (Trace) obj;
				T.reset(this.Kernel);
			// TO DO //
	
				res.add(T);
			}
			catch (java.io.EOFException E){
				break;
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}  
			
		
		//}

		ois.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return res;
	}

	/**
	 * 
	 * @param T trace to add 
	 */
	//int flush =0 ;
	public void addTrace (Trace T){
		//return;
	//	flush++;
	try {
		if(T instanceof powerTrace){
			powerTrace P =(powerTrace) T; 
			//this.powerSet.add(T);
			outpowerSet.writeObject(P);
			outpowerSet.flush();
			outpowerSet.reset();
		}
		if(T instanceof CpuTrace){
			Tasks.add(((CpuTrace) T).getTask());
		//	this.cpuSet.add(T);
			
				
				outCpuSet.writeObject(T);
				outCpuSet.flush();
				outCpuSet.reset();
				
				// this.getArrayfromF(this.cputmp);
			
		}
		if(T instanceof TaskTrace){
		//	this.taskSet.add(T);
			this.outTaskSet.writeObject(T);
			outTaskSet.flush();
			outTaskSet.reset();
			}
		if(T instanceof messageTrace){
			//this.messSet.add(T);
			
			outmessSet.writeObject(T);
			outmessSet.flush();
			outmessSet.reset();
		}
		if(T instanceof DVSTrace){
			outDVSSet.writeObject(T);
			outDVSSet.flush();
			outDVSSet.reset();
		}
		if(T instanceof penalityTrace){
		
			outpenalitySet.writeObject(T);
			outpenalitySet.flush();
			outpenalitySet.reset();
		}
		
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
	/**
	 * !!! Be carefull this fucntion is important to init internal compteur 
	 * @return
	 */
	public int getNbreCpu(){
		int k=0;
		ArrayList cpuSet=null;
			cpuSet = this.getArrayfromF(this.cputmp);
	
		CpuTrace T2=null;
		//Iterator i = this.cpuSet.iterator();
		Iterator i = cpuSet.iterator();
		while(i.hasNext()){
			Trace T=(Trace) i.next();
			if(T instanceof CpuTrace) {
				T2 = (CpuTrace) T;
				CPUs.add(T2.CPU);
			}
		}
		
		return CPUs.size();
		
	}
	/**
	 * 
	 * @return
	 */
	public String totxtFile(){
		String res = "";
		
		
		/**
		 * Trace Processor
		 */
		//Iterator i = this.cpuSet.iterator();
		ArrayList cpuSet=null;
			cpuSet = this.getArrayfromF(this.cputmp);
	
		Iterator i = cpuSet.iterator();
		while(i.hasNext()){
			Trace T=(Trace) i.next();
			
			res = res + T.totxtFile() + "\n";
			if(T instanceof CpuTrace) {
				CpuTrace T1 = (CpuTrace) T;
			
			}
		}
		
		
		Iterator j= Tasks.iterator();
		while(j.hasNext()){
			Task T=(Task) j.next();
			//i = this.cpuSet.iterator();
			i = cpuSet.iterator();
			while(i.hasNext()){
				Trace log=(Trace) i.next();
				if(log instanceof CpuTrace) {
					CpuTrace T1 = (CpuTrace) log;
					if (T1.task ==T){
						res = res + (T1.task + " " +  log.date + " "+ (log.date + 1) + " " + T1.CPU + "\n");
					}
				}
				
			}
			
		}
		return res;
		
	}
	/**
	 * @deprecated 
	 * @since 3.0
	 * @param i
	 * @return
	 */
	public ArrayList<Trace> getEvtTask(int i) {
		ArrayList res=new ArrayList();
		Task  TR=null;
		Iterator j = this.Tasks.iterator();
		while (i!=-1) {
			i--;
			TR= (Task) j.next();
			
		}
		
		ArrayList taskSet=null;
		taskSet = this.getArrayfromF(this.tasktmp);
		
		Iterator k = taskSet.iterator();
		while(k.hasNext()){
			TaskTrace T=(TaskTrace) k.next();
			if (T.task == TR){
				res.add(T);
			}
		}
		return res;
		
	}
	/**
	 * @param i
	 * @return
	 */
	public ArrayList<Trace> getEvtTaskById(int i) {
		
		ArrayList res=new ArrayList();
		Task  TR=null;
		Iterator j = this.Tasks.iterator();
		while (j.hasNext()){
			TR= (Task) j.next();
			if (TR.getId() == i ) {
				break;
			}
			else TR=null;
		}
		if (TR == null) return null;
		
		
		ArrayList taskSet=null;
		taskSet = this.getArrayfromF(this.tasktmp);
		Iterator k = taskSet.iterator();
		while(k.hasNext()){
			TaskTrace T=(TaskTrace) k.next();
			if (T.task == TR){
				res.add(T);
			}
		}
		return res;
		
	}
	/**
	 * @deprecated 
	 * @since 3.0
	 * @param i
	 * @return
	 */
	public ArrayList<Trace> getHistoTask(int i) {
		ArrayList res=new ArrayList();
		Task  TR=null;
		Iterator j = this.Tasks.iterator();
		while (i!=-1) {
			i--;
			TR= (Task) j.next();
			
		}
		ArrayList cpuSet=null;
			cpuSet = this.getArrayfromF(this.cputmp);

		
	//Iterator k = this.cpuSet.iterator();
		Iterator k = cpuSet.iterator();
		while(k.hasNext()){
			Trace T=(Trace) k.next();
			if(T instanceof CpuTrace) {
				CpuTrace T2 = (CpuTrace) T;
				if (T2.task == TR) {
					res.add(T2);
				//System.out.println(T2.date);
				}
			}
			
		}
		
		
		
		return res;
	}
	/**
	 * @deprecated 
	 * @since 3.0
	 * @param i
	 * @return
	 */
	public ArrayList<Trace> getHistoCPU(int i) {
		// TODO Auto-generated method stub
		ArrayList res=new ArrayList();
		
		
		Iterator j = this.CPUs.iterator();
		Processor P=null;
		while (i!=-1) {
			i--;
			P = (Processor) j.next();
			
		}
		ArrayList cpuSet=null;
			cpuSet = this.getArrayfromF(this.cputmp);

		
		//Iterator k = this.cpuSet.iterator();
		Iterator k = cpuSet.iterator();
		while(k.hasNext()){
			Trace T=(Trace) k.next();
			if(T instanceof CpuTrace) {
				CpuTrace T2 = (CpuTrace) T;
				if (T2.CPU == P) {res.add(T2);
				//System.out.println(T2.date);
				}
			}
			
		}
		
		return res;
	}
/**
 * 	 @deprecated 
	 * @since 3.0
 * @param j
 * @return
 */
	public String getCPUName(int j) {
		String res2="";
		ArrayList res=new ArrayList();
		getNbreCpu();
		Iterator k = this.CPUs.iterator();
		Processor P=null;
		
		while (j!=-1) {
			j--;
			P = (Processor) k.next();
			
		}
		res2 = P.name;
		return res2;
	}
/**
 * 
 * @param j
 * @return
 */
	public String getCPUNameById (int j){
		String res2="";
		
		getNbreCpu();
		Iterator k = this.CPUs.iterator();
		Processor P=null;
		while(k.hasNext()){
			P = (Processor) k.next();
			if (P.getId()==j){
				res2 = P.getName();
				break;
			
			}
			
		}
		return res2;
	}
	/**
	 * @deprecated 
	 * @since 3.0
	 * @return
	 */
	public int getNbreTask() {
		return this.Tasks.size();
	}
	/**
	 * 
	 * @param k
	 * @return
	 */
	public String getTaskNameByid(int k) {
		String res2="";
		
		Iterator m = this.Tasks.iterator();
		Task T=null;
		while (m.hasNext()){
			T = (Task) m.next();
			if (T.getId() == k) res2= T.getName();
		}
		return res2;
	}
	/**
	 * @deprecated 
	 * @since 3.0
	 * @param k
	 * @return
	 */
	public String getTaskName(int k) {
		String res2="";
		
		Iterator m = this.Tasks.iterator();
		Task T=null;
		while (k!=-1) {
			k--;
			T = (Task) m.next();
			
		}
		res2 = T.name;
		return res2;
	}

/**
 * 
 * @param simulationKernel
 */
	public void init(SimulationKernel simulationKernel) {
			this.ListeEntities = simulationKernel.listeEntities;
	}
	/**
	 * 
	 * 
	 */
	public int getEvtTaskDurationById(int k) {
		int res = 0;
		
		Iterator m = this.Tasks.iterator();
		Task T=null;
		do {
			
			T = (Task) m.next();
			
		}while (k!=T.getId());
		res = T.activationDate;
		return res;
	}
	/**
	 * 
	 * @param k
	 * @return
	 */
	public int getEvtTaskDuration(int k) {
		int res = 0;
		
		Iterator m = this.Tasks.iterator();
		Task T=null;
		while (k!=-1) {
			k--;
			T = (Task) m.next();
			
		}
		res = T.activationDate;
		return res;
	}
	/**
	 * @deprecated 
	 * @since 3.0
	 * retourne arraylist on i CPU rank
	 */
	public ArrayList getHistoPower(int i) {
		ArrayList res=new ArrayList();
		//To do Bug avec plotpower qui nécessite une init de CPUs
		getNbreCpu();
		//*//
		Iterator j = this.CPUs.iterator();
		Processor P=null;
		while (i!=-1) {
			i--;
			P = (Processor) j.next();
			
		}
		ArrayList powerSet=null;
		powerSet = this.getArrayfromF(this.powertmp);
		
		Iterator k = powerSet.iterator();
		while(k.hasNext()){
			powerTrace T=(powerTrace) k.next();
			
			
				if (T.CPU == P) {
					res.add(T);
				   // System.out.println(T.power);
				}
				
			}
			return res;
		}
	/**
	 * 	With Id value
	 * @param i
	 * @return
	 */

	public ArrayList getHistoPowerbyId (int i){
		ArrayList res=new ArrayList();
		getNbreCpu();
		Iterator j = this.CPUs.iterator();
		
		Processor P=null;
		
		
		while (j.hasNext()) {
			P = (Processor) j.next();
			if (P.getId() == i) break;
			else P= null;
			
			
			
			
		}
	//	System.out.println(P);

		if (P==null) {
			res = null;
			return res;
		}
		ArrayList powerSet=null;
		powerSet = this.getArrayfromF(this.powertmp);
		Iterator k = powerSet.iterator();
		

		while(k.hasNext()){
			powerTrace T=(powerTrace) k.next();
			
			
				if (T.CPU == P) {
					res.add(T);
				   // System.out.println(T.power);
				}
				
			}
			return res;
		
	}
	/*** 
	 * Version V4 
	 */
	public ArrayList<Trace> getHistoTaskById(int deb , int fin, Task task) {
		ArrayList res=new ArrayList();
		
		
		ArrayList taskSet=null;
	//	System.out.println("R11 -> " + System.currentTimeMillis( ));
		taskSet = this.getArrayfromF(this.tasktmp);
	//	System.out.println("R12 -> " + System.currentTimeMillis( ));
	//Iterator k = this.cpuSet.iterator();
	Iterator k = taskSet.iterator();
	while(k.hasNext()){
	
		Trace T=(Trace) k.next();
		
		if(T instanceof TaskTrace) {
			TaskTrace T2 = (TaskTrace) T;
			if (T2.task == task) {
				res.add(T2);
			}
		}
	}
		
		return res;
		
	}
	/*** 
	 * 
	 * Version V4 
	 */
	public ArrayList<Trace> getHistoCPUById(int deb , int fin, int id) {
	
		ArrayList res=new ArrayList();
		getNbreCpu();
		Iterator j = this.CPUs.iterator();
		Processor P=null;
		while(j.hasNext()){
			 P= (Processor) j.next();
			if (P.getId() == id ) {
				break;
			}
			else P=null;
		}
		if (P == null ) return null;
		ArrayList cpuSet=null;
		cpuSet = this.getArrayfromF(this.cputmp);
		
		Iterator k = cpuSet.iterator();
		
		while(k.hasNext()){
			CpuTrace T=(CpuTrace) k.next();
			if ((T.date >= deb ) && (T.date <=  fin) && (T.CPU.id == id)){
				res.add(T);
			}
		
		}
		
		
		return res;
		
		
	}
	
	/**
	 * 
	 * @param i
	 * @return
	 */
	public ArrayList<Trace> getHistoCPUById(int i) {
		ArrayList res=new ArrayList();
		getNbreCpu();
		Iterator j = this.CPUs.iterator();
		Processor P=null;
		while(j.hasNext()){
			 P= (Processor) j.next();
			if (P.getId() == i ) {
				break;
			}
			else P=null;
		}
		if (P == null ) return null;
		
		ArrayList cpuSet=null;
			cpuSet = this.getArrayfromF(this.cputmp);

		//Iterator k = this.cpuSet.iterator();
		Iterator k = cpuSet.iterator();
		while(k.hasNext()){
			Trace T=(Trace) k.next();
			if(T instanceof CpuTrace) {
				CpuTrace T2 = (CpuTrace) T;
				if (T2.CPU == P) {res.add(T2);
				}
			}
			
		}
		
		return res;
	}
	/**
	 * 
	 * @param i
	 * @return
	 */
	public ArrayList<Trace> getHistoTaskById(int i) {
		
		ArrayList res=new ArrayList();
		Task  TR=null;
		Iterator j = this.Tasks.iterator();
		while (j.hasNext()){
			TR= (Task) j.next();
		//	if (TR !=null){
			if (TR.getId()==i) {
				break;
			}
			//}
			else TR=null;
		}
		if (TR == null ) return null;
		ArrayList cpuSet=null;
			cpuSet = this.getArrayfromF(this.cputmp);

		//Iterator k = this.cpuSet.iterator();
		Iterator k = cpuSet.iterator();
		while(k.hasNext()){
			Trace T=(Trace) k.next();
			if(T instanceof CpuTrace) {
				CpuTrace T2 = (CpuTrace) T;
				if (T2.task == TR) {
					res.add(T2);
				}
			}
			
		}
		return res;
	}
	public void freeAll() {
	//	this.cpuSet = new ArrayList<Trace>();
		//this.taskSet = new ArrayList<Trace>();
	//this.powerSet = new ArrayList<Trace>();
		this.Tasks = new HashSet<Task>();
//		this.messSet = new  ArrayList<Trace>();
	//	this.DVSSet = new  ArrayList<Trace>();
	//	this.penalitySet = new  ArrayList<Trace>();
		CPUs = new HashSet<Processor>();
		// TODO Auto-generated method stub
		
	}
		
	
	public class EndOfStreamSignal implements Serializable {}


	public void setKernel(ISimulationKernel simulationKernel) {
		this.Kernel = simulationKernel;
		// TODO Auto-generated method stub
		
	}
	public ArrayList getDVSSet() {
		// TODO Auto-generated method stub
		return 	 this.getArrayfromF(this.DVStmp);
	}
	public ArrayList getmessSet() {
		// TODO Auto-generated method stub
		return 	 this.getArrayfromF(this.messtmp);
	}
	public ArrayList getpenalitySet() {
		// TODO Auto-generated method stub
		return 	 this.getArrayfromF(this.penalitytmp);
	}
	
	/**
	 * V 4
	 * @param i
	 * @param debut
	 * @param end
	 * @return
	 */
	public ArrayList getHistoPowerCPUById( Processor P, int debut, int end) {
		// TODO Auto-generated method stub
		ArrayList res= new ArrayList();
		ArrayList  tmp = 	this.getArrayfromF(powertmp);
		
		Iterator k = tmp.iterator() ;
		while (k.hasNext()){
			log.powerTrace T = (powerTrace) k.next();
			if ((T.date >= debut ) && (T.date <=  end) && (T.CPU.id == P.id)){
				res.add(T);
		
			}
			
		}
		
		
		
		
		return res;
	}  
	
/*	public void finalize()
	{
		System.err.println("Objet nettoyé de la mémoire");   
	}*/
	
}
